﻿using System;
using System.Configuration;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Linq;

namespace POCOFirst
{
	partial class JimmyContext : DbContext
	{
		static JimmyContext()
		{
			Database.DefaultConnectionFactory = new PocoConnectionFactory();
			Database.SetInitializer(new DropCreateDatabaseIfModelChanges<JimmyContext>());
		}
	}

	public class PocoConnectionFactory : IDbConnectionFactory
	{
		public DbConnection CreateConnection(string nameOrConnectionString)
		{
			// connectionString="Data Source=CASPER-PC\SQL_Abbey;Database=Jimmy;Integrated Security=True"
			var builder = new SqlConnectionStringBuilder
			{
				DataSource = @"CASPER-PC\SQL_Abbey",
				InitialCatalog = @"Jimmy",
				IntegratedSecurity = true,
				MultipleActiveResultSets = true
			};

			return new SqlConnection(builder.ToString());
		}
	}

	public class DevartConnectionFactory : IDbConnectionFactory
	{
		public DevartConnectionFactory(string providerInvariantName, string configFileName)
		{
			this.ProviderInvariantName = providerInvariantName;
			this.ConfigFileName = configFileName;
		}

		public DbConnection CreateConnection(string nameOrConnectionString)
		{
			if (String.IsNullOrWhiteSpace(nameOrConnectionString))
				throw new ArgumentNullException("nameOrConnectionString");

			DbProviderFactory providerFactory = DbProviderFactories.GetFactory(ProviderInvariantName);
			if (providerFactory == null)
				throw new InvalidOperationException(String.Format("The '{0}' provider is not registered on the local machine.",
																	ProviderInvariantName));

			DbConnection connection = providerFactory.CreateConnection();

			if (nameOrConnectionString.Contains("="))
				connection.ConnectionString = nameOrConnectionString;
			else
			{
				string dbContextClassName = nameOrConnectionString;
				if (dbContextClassName.Contains('.'))
				{
					int classNameFrom = nameOrConnectionString.LastIndexOf('.') + 1;
					int classNameLength = nameOrConnectionString.Length - classNameFrom;
					dbContextClassName = nameOrConnectionString.Substring(classNameFrom, classNameLength);
				}

				ExeConfigurationFileMap map = new ExeConfigurationFileMap();
				map.ExeConfigFilename = this.ConfigFileName;
				Configuration assemblyConfig = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);

				ConnectionStringSettings connectionSettings = assemblyConfig.ConnectionStrings.ConnectionStrings[dbContextClassName];

				if (connectionSettings == null)
					throw new InvalidOperationException(String.Format("Can't find the '{0}' connection string in the config file.",
																		dbContextClassName));

				if (connectionSettings.ProviderName != ProviderInvariantName)
					throw new InvalidOperationException(
						String.Format(
							"The '{0}' connection string was expected to be defined for the '{1}' provider, but it is defined for the '{2}' provider.",
							dbContextClassName, ProviderInvariantName, connectionSettings.ProviderName));

				connection.ConnectionString = connectionSettings.ConnectionString;
			}

			return connection;
		}

		public string ProviderInvariantName { get; set; }
		public string ConfigFileName { get; set; }
	}
}